﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Hosting;
using AiBLSmartEdu.Module.AIMedicalAssistant.API.Services;
using AiBLSmartEdu.Module.AIMedicalAssistant.API.Configurations;
using ChromaDB.Client;
using FrameworkCore.DI;
using Domain.Entities;
using FrameworkCore.Repositories;
using AiBLSmartEdu.Module.AIMedicalAssistant.API.DTOs;
using FrameworkCore.Helpers;
using Microsoft.AspNetCore.Http;
using FrameworkCore.Constants;
using Microsoft.Extensions.Configuration;
using FrameworkCore.Interfaces;
using FrameworkCore.Models;
using AutoMapper;
using FrameworkCore.Extensions;

#nullable disable

public class KnowledgeBaseService : ITransientDependency
{
    private readonly IOptions<KnowledgeBaseSettings> _options;
    private readonly EmbeddingGenerator _embeddingGenerator;
    //private readonly ChromaCollectionClient _collectionClient;
    private readonly ChromaClientService _chromaClientService;
    private readonly IWebHostEnvironment _env;
    private readonly ILogger<KnowledgeBaseService> _logger;
    private readonly IRepository<KnowledgeBase> _knowledgeBaseRepository;
    private readonly HttpClient _httpClient;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ICurrentUserService _currentUserService;
    private readonly IMapper _mapper;


    public KnowledgeBaseService(
        IOptions<KnowledgeBaseSettings> options,
        EmbeddingGenerator embeddingGenerator,
        ChromaClientService chromaClientService,
        IWebHostEnvironment env,
        ILogger<KnowledgeBaseService> logger,
        IRepository<KnowledgeBase> knowledgeBaseRepository,
        IHttpContextAccessor httpContextAccessor,
        ICurrentUserService currentUserService,
        IMapper mapper)
    {
        _options = options;
        _embeddingGenerator = embeddingGenerator;
        // _collectionClient = chromaClientService.GetCollectionClient();
        _chromaClientService = chromaClientService;
        _env = env;
        _logger = logger;
        _knowledgeBaseRepository = knowledgeBaseRepository;
        _httpClient = new HttpClient();
        _httpContextAccessor = httpContextAccessor;
        _currentUserService = currentUserService;
        _mapper = mapper;
    }

    public async Task InitializeKnowledgeBaseAsync(long knowledgeBaseId)
    {
        try
        {
            var collectionClient = _chromaClientService.GetCollectionClient(knowledgeBaseId.ToString());

            var texts = await ReadTextsFromDbAsync(knowledgeBaseId);
            texts = texts.Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();

            int batchSize = _options.Value.BatchSize;
            for (int i = 0; i < texts.Length; i += batchSize)
            {
                var batchTexts = texts.Skip(i).Take(batchSize).ToArray();
                var batchEmbeddings = new List<float[]>();

                foreach (var text in batchTexts)
                {
                    try
                    {
                        var embedding = await _embeddingGenerator.GenerateEmbeddingAsync(text, 384);
                        if (embedding != null && embedding.Length > 0)
                        {
                            batchEmbeddings.Add(embedding);
                            _logger.LogInformation($"成功生成向量，长度：{embedding.Length}");
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"生成向量时出错：{ex.Message}");
                        continue;
                    }
                }

                if (batchEmbeddings.Count > 0)
                {
                    try
                    {
                        await collectionClient.Add(
                            ids: batchTexts.Take(batchEmbeddings.Count).Select((_, idx) => $"doc_{i + idx}").ToList(),
                            embeddings: batchEmbeddings.Select(embed => new ReadOnlyMemory<float>(embed)).ToList(),
                            metadatas: batchTexts.Take(batchEmbeddings.Count).Select(t => new Dictionary<string, object> { { "content", t } }).ToList()
                        );
                        _logger.LogInformation($"成功插入 {batchEmbeddings.Count} 条数据");
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"插入数据时出错：{ex.Message}");
                    }
                }

                await Task.Delay(1000);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"初始化知识库时出错：{ex.Message}");
            throw;
        }
    }

    private async Task<string[]> ReadTextsFromFileAsync()
    {
        var filePath = Path.Combine(_env.ContentRootPath, _options.Value.KnowledgeFile);
        return await File.ReadAllLinesAsync(filePath);
    }

    private async Task<string[]> ReadTextsFromDbAsync(long knowledgeBaseId)
    {
        var knowledgeBase = await _knowledgeBaseRepository.GetByIdAsync(knowledgeBaseId);
        string[] result = knowledgeBase.Content?.Split(new[] { "\r\n" }, StringSplitOptions.None)
                                 .Where(line => !string.IsNullOrWhiteSpace(line)).ToArray(); // 去除空行;
        return result;
    }

    /// <summary>
    /// 创建知识库
    /// </summary>
    /// <param name="model"></param>
    /// <returns></returns>
    public async Task CreateAsync(KnowledgeBaseCreateInputModel model) 
    {
        ExceptionHelper.ThrowIfNullOrWhiteSpace(model.Url, $"URL不能为空：{nameof(model.Url)}");
        ExceptionHelper.ThrowIfNullOrWhiteSpace(model.Title, $"知识库名称不能为空：{nameof(model.Title)}");

        try
        {
            var exist = _knowledgeBaseRepository.Query(x => x.Title == model.Title && _currentUserService.UserId == x.CreatedBy).Any();
            ExceptionHelper.ThrowIfTrue(exist, $"知识库名称重复：{nameof(model.Title)}");
            var host = ConfigurationsExtensions.GetGlobalSection<string>(GlobalConstants.HostsKey);
            var requestUrl = host.Replace("*", "192.168.0.22");
            if (!model.Url.StartsWith("/") && !requestUrl.EndsWith("/"))
            {
                requestUrl = $"{requestUrl}/{model.Url}";
            }
            else 
            {
                requestUrl = $"{requestUrl}{model.Url}";
            }
            // 发送 GET 请求并获取响应
            HttpResponseMessage response = await _httpClient.GetAsync(requestUrl);

            // 检查响应是否成功
            response.EnsureSuccessStatusCode();

            // 读取响应内容为字符串
            string fileContent = await response.Content.ReadAsStringAsync();
           await _knowledgeBaseRepository.InsertAsync(new KnowledgeBase { Content= fileContent, Path= model.Url,Title= model.Title });
        }
        catch (HttpRequestException ex)
        {
            // 处理 HTTP 请求异常
            ExceptionHelper.ThrowIfTrue(true, $"请求失败: {ex.Message}");
        }
        catch (Exception ex)
        {
            ExceptionHelper.ThrowIfTrue(true, $"发生错误: {ex.Message}");
        }
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="filter">分页输入模型</param>
    /// <returns></returns>
    public async Task<PageResult<KnowledgeBaseOutputModel>> PageAsync(KnowledgeBasePaginationFilter filter)
    {
        return (await _knowledgeBaseRepository.GetOrderedQueryable(query =>
        {
            return query.OrderByDescending(o => o.Id)
            .WhereIf(!filter.Keyword.IsNullOrWhiteSpace(), x => x.Title.Contains(filter.Keyword));

        }, filter).ProjectToPaginatedDataAsync<KnowledgeBase, KnowledgeBaseOutputModel>(
            filter.PageNumber,
            filter.PageSize,
            _mapper.ConfigurationProvider
        )).ToPageList();
    }

    /// <summary>
    /// 删除知识库
    /// </summary>
    /// <param name="knowledgeBaseId"></param>
    /// <returns></returns>
    public async Task DeleteAsync(long knowledgeBaseId)
    {
        var knowledgeBase = await _knowledgeBaseRepository.GetByIdAsync(knowledgeBaseId);
        ExceptionHelper.ThrowIfNull(knowledgeBase, "知识库不存在");
        await _knowledgeBaseRepository.DeleteAsync(knowledgeBase);
    }
}